passthrough: use tasklet to deliver interrupts
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 28 Jul 2009 15:28:21 +0000 (16:28 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 28 Jul 2009 15:28:21 +0000 (16:28 +0100)
This patch enables delivery of interrupts even if the VCPU#0 is
halted.

Note: the changes to softirq.{ch} are needed for ia64 build.

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
xen/arch/ia64/vmx/vmx_fault.c
xen/arch/x86/hvm/svm/intr.c
xen/arch/x86/hvm/vmx/intr.c
xen/common/softirq.c
xen/drivers/passthrough/io.c
xen/drivers/passthrough/pci.c
xen/include/xen/hvm/irq.h
xen/include/xen/softirq.h

index 53d0693876659a052f61bda5fab6686068947bda..642d3120c22aaba3a7537f17309655399f573990 100644 (file)
@@ -305,7 +305,6 @@ void leave_hypervisor_tail(void)
                 viosapic_set_irq(d, callback_irq, 0);
             }
         }
-        hvm_dirq_assist(v);
     }
 
     rmb();
index b6499070c0c6d20d1c582633dbc2ca665e1c49d0..369423612b4b4f8f6e006c7b26382380b3b56829 100644 (file)
@@ -109,7 +109,6 @@ asmlinkage void svm_intr_assist(void)
 
     /* Crank the handle on interrupt state. */
     pt_update_irq(v);
-    hvm_dirq_assist(v);
 
     do {
         intack = hvm_vcpu_has_pending_irq(v);
index ef536ac8f2ea6bb0f6c9afb96c50a90d8890281e..299b7d2c2bcd38f3f61c774478d573437d6f082c 100644 (file)
@@ -127,7 +127,6 @@ asmlinkage void vmx_intr_assist(void)
 
     /* Crank the handle on interrupt state. */
     pt_update_irq(v);
-    hvm_dirq_assist(v);
 
     do {
         intack = hvm_vcpu_has_pending_irq(v);
index a4ae6a0c62d0bf3b94da6f6b46abd48118bca063..ecf33793889fdfa01818636afd34fdaf3c9aaed2 100644 (file)
@@ -53,6 +53,28 @@ void open_softirq(int nr, softirq_handler handler)
     softirq_handlers[nr] = handler;
 }
 
+void cpumask_raise_softirq(cpumask_t mask, unsigned int nr)
+{
+    int cpu;
+
+    for_each_cpu_mask(cpu, mask)
+        if ( test_and_set_bit(nr, &softirq_pending(cpu)) )
+            cpu_clear(cpu, mask);
+
+    smp_send_event_check_mask(&mask);
+}
+
+void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
+{
+    if ( !test_and_set_bit(nr, &softirq_pending(cpu)) )
+        smp_send_event_check_cpu(cpu);
+}
+
+void raise_softirq(unsigned int nr)
+{
+    set_bit(nr, &softirq_pending(smp_processor_id()));
+}
+
 static LIST_HEAD(tasklet_list);
 static DEFINE_SPINLOCK(tasklet_lock);
 
index 61060db8e38b7da355ea3e6419cade27b603c7bd..97de764536160c116e773a77cbc71892c80bbe98 100644 (file)
@@ -24,6 +24,8 @@
 #include <asm/hvm/iommu.h>
 #include <xen/hvm/irq.h>
 
+static void hvm_dirq_assist(unsigned long _d);
+
 static int pt_irq_need_timer(uint32_t flags)
 {
     return !(flags & (HVM_IRQ_DPCI_GUEST_MSI | HVM_IRQ_DPCI_TRANSLATE));
@@ -114,6 +116,8 @@ int pt_irq_create_bind_vtd(
             return -ENOMEM;
         }
         memset(hvm_irq_dpci, 0, sizeof(*hvm_irq_dpci));
+        tasklet_init(&hvm_irq_dpci->dirq_tasklet, 
+                     hvm_dirq_assist, (unsigned long)d);
         hvm_irq_dpci->mirq = xmalloc_array(struct hvm_mirq_dpci_mapping,
                                            d->nr_pirqs);
         hvm_irq_dpci->dirq_mask = xmalloc_array(unsigned long,
@@ -368,18 +372,8 @@ int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq)
          !test_bit(mirq, dpci->mapping))
         return 0;
 
-    /*
-     * Set a timer here to avoid situations where the IRQ line is shared, and
-     * the device belonging to the pass-through guest is not yet active. In
-     * this case the guest may not pick up the interrupt (e.g., masked at the
-     * PIC) and we need to detect that.
-     */
     set_bit(mirq, dpci->dirq_mask);
-    if ( pt_irq_need_timer(dpci->mirq[mirq].flags) )
-        set_timer(&dpci->hvm_timer[domain_irq_to_vector(d, mirq)],
-                  NOW() + PT_IRQ_TIME_OUT);
-    vcpu_kick(d->vcpu[0]);
-
+    tasklet_schedule(&dpci->dirq_tasklet);
     return 1;
 }
 
@@ -429,16 +423,15 @@ static int hvm_pci_msi_assert(struct domain *d, int pirq)
 }
 #endif
 
-void hvm_dirq_assist(struct vcpu *v)
+static void hvm_dirq_assist(unsigned long _d)
 {
     unsigned int irq;
     uint32_t device, intx;
-    struct domain *d = v->domain;
+    struct domain *d = (struct domain *)_d;
     struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
     struct dev_intx_gsi_link *digl;
 
-    if ( !iommu_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) )
-        return;
+    ASSERT(hvm_irq_dpci);
 
     for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, d->nr_pirqs);
           irq < d->nr_pirqs;
@@ -456,9 +449,6 @@ void hvm_dirq_assist(struct vcpu *v)
             continue;
         }
 #endif
-        if ( pt_irq_need_timer(hvm_irq_dpci->mirq[irq].flags) )
-            stop_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, irq)]);
-
         list_for_each_entry ( digl, &hvm_irq_dpci->mirq[irq].digl_list, list )
         {
             device = digl->device;
index 27699e038ba28b94efa52c648c1b7b88531a8d49..37f1f4ba5c5e36eb60c7a25f1c9b9f57ec75dccb 100644 (file)
@@ -209,6 +209,8 @@ static void pci_clean_dpci_irqs(struct domain *d)
     hvm_irq_dpci = domain_get_irq_dpci(d);
     if ( hvm_irq_dpci != NULL )
     {
+        tasklet_kill(&hvm_irq_dpci->dirq_tasklet);
+
         for ( i = find_first_bit(hvm_irq_dpci->mapping, d->nr_pirqs);
               i < d->nr_pirqs;
               i = find_next_bit(hvm_irq_dpci->mapping, d->nr_pirqs, i + 1) )
index 4fe118c31b7ec72789a03d9225498901e0b7fcf2..b50cff6da94990f9f2f32ce284bfe5801e53e79e 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <xen/types.h>
 #include <xen/spinlock.h>
+#include <xen/softirq.h>
 #include <asm/irq.h>
 #include <public/hvm/save.h>
 
@@ -88,6 +89,7 @@ struct hvm_irq_dpci {
     /* Record of mapped Links */
     uint8_t link_cnt[NR_LINK];
     struct timer hvm_timer[NR_VECTORS];
+    struct tasklet dirq_tasklet;
 };
 
 /* Modify state of a PCI INTx wire. */
@@ -108,6 +110,4 @@ void hvm_maybe_deassert_evtchn_irq(void);
 void hvm_assert_evtchn_irq(struct vcpu *v);
 void hvm_set_callback_via(struct domain *d, uint64_t via);
 
-void hvm_dirq_assist(struct vcpu *v);
-
 #endif /* __XEN_HVM_IRQ_H__ */
index efd0a544438e780804c5ab9fc59d7111af808058..5d5661fd43e65d29f0d4ac131c3eabd61f539b4f 100644 (file)
@@ -29,29 +29,9 @@ asmlinkage void do_softirq(void);
 void open_softirq(int nr, softirq_handler handler);
 void softirq_init(void);
 
-static inline void cpumask_raise_softirq(cpumask_t mask, unsigned int nr)
-{
-    int cpu;
-
-    for_each_cpu_mask(cpu, mask)
-    {
-        if ( test_and_set_bit(nr, &softirq_pending(cpu)) )
-            cpu_clear(cpu, mask);
-    }
-
-    smp_send_event_check_mask(&mask);
-}
-
-static inline void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
-{
-    if ( !test_and_set_bit(nr, &softirq_pending(cpu)) )
-        smp_send_event_check_cpu(cpu);
-}
-
-static inline void raise_softirq(unsigned int nr)
-{
-    set_bit(nr, &softirq_pending(smp_processor_id()));
-}
+void cpumask_raise_softirq(cpumask_t mask, unsigned int nr);
+void cpu_raise_softirq(unsigned int cpu, unsigned int nr);
+void raise_softirq(unsigned int nr);
 
 /*
  * TASKLETS -- dynamically-allocatable tasks run in softirq context